using System.Diagnostics;
using System.Text;
using System.Xml.Serialization;

namespace G_Code_Postprocessor
{
    
    public partial class MainForm : Form
    {
        public static TransitionTypeForm TransitionTypeForm1 = new TransitionTypeForm();
        public static InstallPieceForm InstallPieceForm1 = new InstallPieceForm();
        public static UninstallPieceForm UninstallPieceForm1 = new UninstallPieceForm();
        public static ShoulderTurningForm ShoulderTurningForm1 = new ShoulderTurningForm();
        public static FacingForm FacingForm1 = new FacingForm();
        public static TaperTurningForm TaperTurningForm1 = new TaperTurningForm();
        public static RadiusTurningClockwiseForm RadiusTurningClockwiseForm1 = new RadiusTurningClockwiseForm();
        public static RadiusTurningAnticlockwiseForm RadiusTurningAnticlockwiseForm1 = new RadiusTurningAnticlockwiseForm();

        public static CirclePiece circlePiece = new CirclePiece();
        public static List<Transition> transitions = new List<Transition>();

        public static bool editTransition = false;

        public static int AddTransition(TransitionType ransitionType, int selindex)
        {
            if (!editTransition)
            {
                if (selindex < 0)
                {
                    transitions.Add(new Transition());
                    selindex = transitions.Count() - 1;
                }
                else
                {
                    transitions.Insert(++selindex, new Transition());
                }
                transitions[selindex].Init(ransitionType);
            }
            /*
            if (!editTransition)
            {
                transitions.Add(new Transition());
                selindex = transitions.Count() - 1;
                transitions[selindex].Init(ransitionType);
            }*/
            return selindex;
        }

        public static T TLoad<T>(string FileSpec)
        {
            XmlSerializer formatter = new XmlSerializer(typeof(T));

            using (FileStream aFile = new FileStream(FileSpec, FileMode.Open))
            {
                byte[] buffer = new byte[aFile.Length];
                aFile.Read(buffer, 0, (int)aFile.Length);

                using (MemoryStream stream = new MemoryStream(buffer))
                {
                    return (T)formatter.Deserialize(stream);
                }
                aFile.Close();
            }
        }

        public static void TSave<T>(T ToSerialize, string FileSpec)
        {
            Directory.CreateDirectory(FileSpec.Substring(0, FileSpec.LastIndexOf('\\')));
            FileStream outFile = File.Create(FileSpec);
            XmlSerializer formatter = new XmlSerializer(typeof(T));

            formatter.Serialize(outFile, ToSerialize);
            outFile.Close();
        }
        
        public MainForm(string[] args)
        {
            InitializeComponent();
            if (args.Length > 0)
            if (File.Exists(args[0]))
                transitions = TLoad<List<Transition>>(args[0]);
            UpdateTransitions();
            //����� ���� ����� ������ ������� � ������:
            System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo("en-US");
        }
        public void UpdateButtons()
        {
            if (lBoxTransitions.SelectedIndex < 0)
            {
                btRemoveTransition.Enabled = false;
                btEdit.Enabled = false;
                btTransitionUp.Enabled = false;
                btTransitionDown.Enabled = false;
            }
            else
            {
                btRemoveTransition.Enabled = true;
                btEdit.Enabled = true;
                btTransitionUp.Enabled = true;
                btTransitionDown.Enabled = true;
            }
            if (transitions.Count == 0)
            {
                btClear.Enabled = false;
                btSaveTransitions.Enabled = false;
                btGenerateGcode.Enabled = false;
                btSaveGcode.Enabled = false;
            }
            else
            {
                btClear.Enabled = true;
                btSaveTransitions.Enabled = true;
                btGenerateGcode.Enabled = true;
                btSaveGcode.Enabled = true;
            }
        }
        public void UpdateTransitions()
        {
            lBoxTransitions.Items.Clear();
            tBoxGcode.Text = "";
            int cnt = 0;
            bool frnum = checkBoxFrameNumbers.Checked;
            for (int i = 0; i < transitions.Count; i++)
            {
                lBoxTransitions.Items.Add((i + 1) + ". " + transitions[i].description);
                cnt += (i == 0) ? 0 : transitions[i - 1].gcode.frames.Count;
                transitions[i].GenerateGcode(cnt, frnum);
                tBoxGcode.Text += transitions[i].gcode.GetGcode();
            }
            UpdateButtons();
        }

        public static void ShowForm(TransForm form, TransForm mainform)
        {
            form.StartPosition = FormStartPosition.Manual;
            form.Left = mainform.Left;
            form.Top = mainform.Top;
            form.lBoxTransitions = mainform.lBoxTransitions;
            form.Show();
        }
        public static void ShowForm(TransForm form, Form mainform, ListBox listBox)
        {
            form.StartPosition = FormStartPosition.Manual;
            form.Left = mainform.Left;
            form.Top = mainform.Top;
            form.lBoxTransitions = listBox;
            form.Show();
        }

        public void EditTransition(int index)
        {
            editTransition = true;
            switch (transitions[index].transitionType)
            {
                case TransitionType.Install:
                    ShowForm(new InstallPieceForm(), this, lBoxTransitions);
                    break;
                case TransitionType.Uninstall:
                    ShowForm(new UninstallPieceForm(), this, lBoxTransitions);
                    break;
                case TransitionType.ShoulderTurning:
                    ShowForm(new ShoulderTurningForm(), this, lBoxTransitions);
                    break;
                case TransitionType.Facing:
                    ShowForm(new FacingForm(), this, lBoxTransitions);
                    break;
                case TransitionType.TaperTurning:
                    ShowForm(new TaperTurningForm(), this, lBoxTransitions);
                    break;
                case TransitionType.RadiusTurningClockwise:
                    ShowForm(new RadiusTurningClockwiseForm(), this, lBoxTransitions);
                    break;
                case TransitionType.RadiusTurningAnticlockwise:
                    ShowForm(new RadiusTurningAnticlockwiseForm(), this, lBoxTransitions);
                    break;
                default:
                    break;
            }
        }

        public void RemoveTranzition()
        {
            int index = lBoxTransitions.SelectedIndex;
            if (index != -1)
            {
                transitions.RemoveAt(index);
                UpdateTransitions();
                if (lBoxTransitions.Items.Count == 0)
                    btRemoveTransition.Enabled = false;
                else
                {
                    if (lBoxTransitions.Items.Count - 1 < index)
                        index--;
                    lBoxTransitions.SelectedIndex = index;
                }
            }
            UpdateButtons();
        }

        private void btAddTransition_Click(object sender, EventArgs e)
        {
            editTransition = false;
            TransitionTypeForm1 = new TransitionTypeForm();
            TransitionTypeForm1.StartPosition = FormStartPosition.Manual;
            TransitionTypeForm1.Left = this.Left;
            TransitionTypeForm1.Top = this.Top;
            TransitionTypeForm1.lBoxTransitions = this.lBoxTransitions;
            TransitionTypeForm1.Show();
        }

        private void btSaveGcode_Click(object sender, EventArgs e)
        {
            UpdateTransitions();
            SaveFileDialog saveFile1 = new SaveFileDialog();
            saveFile1.DefaultExt = "*.txt";
            saveFile1.Filter = "Text files|*.txt";
            if (saveFile1.ShowDialog() == System.Windows.Forms.DialogResult.OK &&
                saveFile1.FileName.Length > 0)
            {
                tBoxGcode.SaveFile(saveFile1.FileName, System.Windows.Forms.RichTextBoxStreamType.PlainText);
            }
        }

        private void btGenerateGcode_Click(object sender, EventArgs e)
        {
            UpdateTransitions();
            Clipboard.Clear();
            string text = String.Empty;
            for (int i = 0; i < tBoxGcode.Lines.Length; i++)
                text += tBoxGcode.Lines[i] + Environment.NewLine;
            if(text != String.Empty) Clipboard.SetText(text);
        }

        private void lBoxTransitions_SelectedIndexChanged(object sender, EventArgs e)
        {
            UpdateButtons();
        }

        private void btRemoveTransition_Click(object sender, EventArgs e)
        {
            RemoveTranzition();
        }

        private void btUpdateTransitions_Click(object sender, EventArgs e)
        {
            UpdateTransitions();
        }

        private void MainForm_Activated(object sender, EventArgs e)
        {
            UpdateTransitions();
        }

        //������ ������� ��� �������� ���� � ���������
        private void lst_MeasureItem(object sender, MeasureItemEventArgs e)
        {
            e.ItemHeight = (int)e.Graphics.MeasureString(lBoxTransitions.Items[e.Index].ToString(), lBoxTransitions.Font, lBoxTransitions.Width).Height;
        }

        private void lst_DrawItem(object sender, DrawItemEventArgs e)
        {
            if (lBoxTransitions.Items.Count > 0 && e.Index >= 0)
            {
                e.DrawBackground();
                e.DrawFocusRectangle();
                e.Graphics.DrawString(lBoxTransitions.Items[e.Index].ToString(), e.Font, new SolidBrush(e.ForeColor), e.Bounds);
            }
        }
        //��������� ������� ��� �������� ���� � ���������

        

        private void MainForm_Load(object sender, EventArgs e)
        {
            this.Text = Application.ProductName;
            pbSafetyScreen.Visible = true;
            pbSafetyScreen.Location = new Point(0,0);
            pbSafetyScreen.Width = this.Width - 16;
            pbSafetyScreen.Height = this.Height - 39;
            btOk.Left = pbSafetyScreen.Width - btOk.Width - 15;
            btOk.Top = pbSafetyScreen.Height - btOk.Height - 15;

            comboBox1.SelectedIndex = 0;

            //���������� ������ ������ ��������
            /*
            Icon icon = global::G_Code_Postprocessor.Properties.Resources.tof;
            string dir = @"C:\g-coder\icons\";
            if (!Directory.Exists(dir)) Directory.CreateDirectory(dir);
            using (var file = File.Create(dir + "tof.ico"))
                icon.Save(file);
            icon.Dispose();*/

            //�������� ������ ����������� ������
            string dir = @"C:\g-coder\regedit\";
            if (!Directory.Exists(dir)) Directory.CreateDirectory(dir);
             
            string value = Application.ExecutablePath.Replace("\\", "\\\\");
            
            System.IO.File.WriteAllText(dir + "tofico.reg",
                "Windows Registry Editor Version 5.00\n"
                + "\n"
                + "[HKEY_CLASSES_ROOT\\.op]\n"
                + "@=\"" + "opfile" + "\"\n"
                + "\n"
                + "[HKEY_CLASSES_ROOT\\opfile]\n"
                + "@=\"" + "Technological operation file" + "\"\n"
                + "\n"
                + "[HKEY_CLASSES_ROOT\\opfile\\DefaultIcon]\n"
                + "@=\"" + value + ",1" + "\"\n"
                + "\n"
                + "[HKEY_CLASSES_ROOT\\opfile\\shell]\n" 
                + "\n"
                + "[HKEY_CLASSES_ROOT\\opfile\\shell\\open]\n" 
                + "\n"
                + "[HKEY_CLASSES_ROOT\\opfile\\shell\\open\\command]\n"
                + "@=\"" + value + " %1" + "\"\n");
            
            System.IO.File.WriteAllText(dir + "toficodel.reg",
                "Windows Registry Editor Version 5.00\n"
                + "\n"
                + "[-HKEY_CLASSES_ROOT\\.op]"
                + "\n"
                + "[-HKEY_CLASSES_ROOT\\opfile]");

            string keyName = "HKEY_CLASSES_ROOT\\opfile\\DefaultIcon";
            value = Application.ExecutablePath + ",1";
            object valuereg = Microsoft.Win32.Registry.GetValue(keyName, "", null);
            if (String.Equals(valuereg, value))
            {
                //code if key Exist
                checkBox1.Checked = true;
            }
            else
            {
                //code if key Not Exist
                checkBox1.Checked = false;
            }
            /*
            using (Microsoft.Win32.RegistryKey regKey = Microsoft.Win32.Registry.ClassesRoot.OpenSubKey(
            keyName, valueName))
            {
                if (regKey == null)
                    checkBox1.Checked = false;
                else
                    checkBox1.Checked = true;
            }
            */
        }

        private void lBoxTransitions_KeyDown(object sender, KeyEventArgs e)
        {
            switch (e.KeyCode)
            {
                case Keys.Delete:
                    RemoveTranzition();
                break;
                default:

                break;
            }
        }

        private void btClear_Click(object sender, EventArgs e)
        {
            transitions.Clear();
            UpdateTransitions();
        }

        private void btEdit_Click(object sender, EventArgs e)
        {
            int index = lBoxTransitions.SelectedIndex;
            if (transitions.Count > 0 && index > -1) EditTransition(index);
        }

        private void lBoxTransitions_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            int index = lBoxTransitions.SelectedIndex;
            if (transitions.Count > 0 && index > -1) EditTransition(index);
        }

        private void btOk_Click(object sender, EventArgs e)
        {
            pbSafetyScreen.Visible = false;
            btOk.Visible = false;
        }

        private void btSaveTransitions_Click(object sender, EventArgs e)
        {
            if (transitions.Count > 0)
            {
                UpdateTransitions();
                SaveFileDialog saveFile1 = new SaveFileDialog();
                saveFile1.DefaultExt = "*.op";
                saveFile1.Filter = "Operation files|*.op";
                if (saveFile1.ShowDialog() == System.Windows.Forms.DialogResult.OK &&
                    saveFile1.FileName.Length > 0)
                {
                    TSave<List<Transition>>(transitions, saveFile1.FileName);
                    string s = Path.GetFileName(saveFile1.FileName);
                    this.Text = s + " - " + Application.ProductName;
                }
            }
        }

        private void btLoadTransitions_Click(object sender, EventArgs e)
        {
            UpdateTransitions();
            OpenFileDialog openFile1 = new OpenFileDialog();
            openFile1.DefaultExt = "*.op";
            openFile1.Filter = "Operation files|*.op";
            if (openFile1.ShowDialog() == System.Windows.Forms.DialogResult.OK &&
                openFile1.FileName.Length > 0)
            {
                transitions = TLoad<List<Transition>>(openFile1.FileName);
                string s = Path.GetFileName(openFile1.FileName);
                this.Text = s + " - " + Application.ProductName;
            }
            UpdateTransitions();
        }
        private static void regDeleteSubKeyDefaultIcon(string subKey, string key)
        {
            using (Microsoft.Win32.RegistryKey regKey = Microsoft.Win32.Registry.ClassesRoot.OpenSubKey(
            subKey, true))
            {
                if (regKey != null)
                {
                    regKey.DeleteSubKey(key, true);
                }
            }
        }
        private void checkBox1_CheckedChanged(object sender, EventArgs e)
        {
            
        }

        private void checkBox1_Click(object sender, EventArgs e)
        {
            if (checkBox1.Checked)
            {
                string strRegPath = "C:\\g-coder\\regedit\\tofico.reg";
                var proc = new Process();
                var pi = new ProcessStartInfo();
                pi.UseShellExecute = true;
                pi.FileName = strRegPath;
                proc.StartInfo = pi;
                proc.Start();
            }
            else
            {
                string strRegPath = "C:\\g-coder\\regedit\\toficodel.reg";
                var proc = new Process();
                var pi = new ProcessStartInfo();
                pi.UseShellExecute = true;
                pi.FileName = strRegPath;
                proc.StartInfo = pi;
                proc.Start();
            }
        }

        private void btTransitionUp_Click(object sender, EventArgs e)
        {
            int index = lBoxTransitions.SelectedIndex;
            if (index != -1)
            {
                if (index > 0)
                    Ext.Swap(transitions, index, --index);
                UpdateTransitions();
                if (index != -1)
                    lBoxTransitions.SelectedIndex = index;
            }
            UpdateButtons();
        }

        private void btTransitionDown_Click(object sender, EventArgs e)
        {
            int index = lBoxTransitions.SelectedIndex;
            if (index != -1)
            {
                if (index < transitions.Count - 1)
                    Ext.Swap(transitions, index, ++index);
                UpdateTransitions();
                if (index < transitions.Count)
                    lBoxTransitions.SelectedIndex = index;
            }
            UpdateButtons();
        }

        private void checkBoxFrameNumbers_CheckedChanged(object sender, EventArgs e)
        {
            UpdateTransitions();
        }
    }

    static class Ext
    {
        public static void Move<T>(this List<T> list, int i, int j)
        {
            var elem = list[i];
            list.RemoveAt(i);
            list.Insert(j, elem);
        }

        public static void Swap<T>(this List<T> list, int i, int j)
        {
            var elem1 = list[i];
            var elem2 = list[j];

            list[i] = elem2;
            list[j] = elem1;
        }
    }

    public class TransForm : Form
    {
        public ListBox lBoxTransitions = new();

    }
}